/*
 * IGContestImpl.java
 * Created on 23 juin 07
 *
 * Glacéo Internet Platform
 * http://sourceforge.net/projects/chm/
 *
 * Copyright (c) 2005-2007, Jan Janke (VirtualHockey Project)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hockeo.vhbase.data.impl;

import com.hockeo.vhbase.data.dao.IGDao;
import com.hockeo.vhbase.data.dao.contest.GContest;
import com.hockeo.vhbase.data.dao.contest.GContestElement;
import com.hockeo.vhbase.data.dao.contest.GContestRound;
import com.hockeo.vhbase.data.dao.season.GMatchday;
import com.hockeo.vhbase.data.dao.season.GMoveday;
import com.hockeo.vhbase.data.dao.season.GSeason;
import com.hockeo.vhbase.data.impl.goals.IGGoalsDistributor;
import com.hockeo.vhbase.error.GDataException;

/**
 * Interface to be implemented by the classes that define the logic for a specific contest
 * (match creation, matchday analysis, standings creation, end and start of season
 * manipulations etc.).
 *
 * Implementing classes must have a public argumentless constructor.
 *
 * @version $Id$
 * @author jjanke
 */
public interface IGContestImpl
{
  /**
   * Sets the DAO to be used for database interactions.
   *
   * @param dao the DAO to be set
   */
  public void setDao( IGDao dao );

  /**
   * Sets the goals distributor which is used to fill the initial goal accounts.
   *
   * @param goalsDistributor the goals distributor to be used
   */
  public void setGoalsDistributor( IGGoalsDistributor goalsDistributor );

  /**
   * <p>
   * Creates the contest structure (rounds and contest elements) for contests where the
   * structure is not maintained manually.
   * </p>
   * <p>
   * This method is also responsible for assigning clubs to the contest. I.e. contest
   * history objects are created for national or international cup contests.
   * </p>
   *
   * @param season the current season
   * @param contest the contest for which to create the structure
   * @throws GDataException
   */
  public void createStructure( final GSeason season, final GContest contest ) throws GDataException;

  /**
   * This method does exactly the inverse operations compared to the method
   * {@link #createStructure(GSeason, GContest)} and is intended for undo/reset
   * operations.
   *
   * @param season the current season
   * @param contest the contest for which to undo the create structure operations
   * @throws GDataException
   */
  public void undoCreateStructure( final GSeason season, final GContest contest ) throws GDataException;

  /**
   * <p>
   * Deletes structure elements that have been automatically created using the
   * {@link #createStructure(GContest)} method at the beginning of the season. This method
   * is not intended to rollback actions from the <code>createStructure</code> method. It
   * does not necessarily delete all elements created in there (e.g. club/contest history
   * records etc.).
   * </p>
   *
   * <p>
   * This method is intended to be called at the end of the season in order to reestablish
   * a "raw" contest state. Especially contests in which the structure may change every
   * season should provide a non-empty implementation.
   * </p>
   *
   * @param season the current season
   * @param contest the contest for which to delete the structure
   * @throws GDataException
   */
  public void deleteStructure( final GSeason season, final GContest contest ) throws GDataException;

  /**
   * Creates all matchdays of the entire season if they have not yet been created. No
   * matches are attached (yet) to the matchdays.
   *
   * @param contest the contest for which to create the matchdays
   * @throws GDataException if there is a semantical problem (e.g. if there is contest
   *           element which is not supported by the contest)
   */
  public void createMatchdays( GContest contest ) throws GDataException;

  /**
   * Automatically assigns matchdays to movedays. Works according to the following rules:
   *
   * 1) Determines total number of matchdays.
   *
   * 3) Determines how many movedays are available for each contest round.
   *
   * 2) For round robin matches exactly half of the matchdays will be distributed to half
   * of the available movedays. For KO style competitions, all matches of the same round
   * are scheduled to take place at the same moveday.
   *
   * If a contest round contains more than one contest element, it is required that all
   * contest elements have their last matchday at the same moveday!
   *
   * @param contest the contest whose matchdays shall be assigned to movedays
   * @throws GDataException if there is a semantic (game logic) problem hindering the
   *           correct execution of this method
   */
  public void assignMatchdaysToMovedays( GContest contest ) throws GDataException;

  /**
   * Checks if a new contest round needs to be created and if necessary creates the
   * required goal accounts and matches.
   *
   * @param contest the contest for which to create the next contest round
   * @param season the current season
   * @param movedayCurrent the next moveday to be executed
   * @throws GDataException if there is a semantic (game logic) problem hindering the
   *           correct execution of this method
   */
  public void createNextContestRound( GContest contest, GSeason season, GMoveday movedayCurrent ) throws GDataException;

  /**
   * Reverses the actions that have been carried out by the last call to
   * {@link #createNextContestRound(GContest, GMoveday)}.
   *
   * @param contest the contest for which the last preparation of a contest round should
   *          be undone
   * @param movedayLastPrepared the last prepared moveday
   * @throws GDataException
   */
  public void undoCreateNextContestRound( final GContest contest, final GMoveday movedayLastPrepared )
      throws GDataException;

  /**
   * Analyses all matches that have been played at the given matchday in the specified
   * contest. I.e. winners are determined (if necessary by carrying out a shootout
   * session) and standings are updated for round robin style competitions.
   *
   * @param contestElement the contest element for which to analyse matches
   * @param matchday the matchday which should be analysed
   * @throws GDataException if there is a data consistency problem
   */
  public void analyseMatches( final GContestElement contestElement, final GMatchday matchday ) throws GDataException;

  /**
   * This method is called after all contest elements of a specific matchday have been
   * analysed. It is only called for contest rounds that have more than 1 contest element
   * attached and allows to make specific post-processings. E.g. if in a multi RR element
   * round, only the best two second ranked teams should be marked as being promoted etc.
   *
   * @param round the multi-element contest round
   * @param nMatchday the matchday number to be analysed (it is assumed that all elements
   *          of the same contest round have the same number of matchdays and are numbered
   *          in the same way).
   * @throws GDataException
   */
  public void postprocessMultiElementRound( GContestRound round, Integer nMatchday ) throws GDataException;

  /**
   * Resets the goal accounts for the given contest element to the state they were in
   * before the moveday that is specified as parameter has been executed. This only
   * applies to contest elements were multiple movedays span over a single contest
   * element.
   *
   * @param moveday the last executed moveday that is about to be reset
   * @param element the contest element for which to reset the goal accounts
   * @throws GDataException
   */
  public void resetGoalAccounts( final GMoveday moveday, final GContestElement element ) throws GDataException;

  /**
   * Resets the club/contest related statistics that are updated throughout the season.
   * Not all contests may require constantly updated season stats. Therefore in some cases
   * the implementation provided for this method may be empty.
   *
   * @param moveday the last executed moveday that is about to be reset
   * @param element the contest element for which to reset the contest stats
   * @throws GDataException
   */
  public void resetContestStats( final GMoveday moveday, final GContestElement element ) throws GDataException;

  /**
   * Creates all necessary end of season statistics for the given contest element. This
   * method is called directly after the last matchday of the season has been analysed.
   *
   * @param contestElement the contest element for which to create statistics (should be
   *          attached to the last contest round of the whole contest)
   * @throws GDataException if there is a data consistency problem
   */
  public void createEndOfSeasonStatistics( final GContestElement contestElement ) throws GDataException;

  /**
   * Removes all possibly existing end of season statistics for the given contest element
   * and the current season.
   *
   * @param contestElement the contest element for which to remove statistics
   * @throws GDataException if there is a data consistency problem
   */
  public void deleteEndOfSeasonStatistics( final GContestElement contestElement ) throws GDataException;
}
